{
  "cells": [
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/pinecone-io/examples/blob/master/learn/generation/langchain/handbook/04-langchain-chat.ipynb) [![Open nbviewer](https://raw.githubusercontent.com/pinecone-io/examples/master/assets/nbviewer-shield.svg)](https://nbviewer.org/github/pinecone-io/examples/blob/master/learn/generation/langchain/handbook/04-langchain-chat.ipynb)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "sdwa2QfAp9pT",
        "outputId": "cfc21d75-c308-45c5-bae2-3b16016a53fb"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.0\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m23.0.1\u001b[0m\n",
            "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n"
          ]
        }
      ],
      "source": [
        "!pip install -qU langchain openai"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "wnXqS4T_q5m4"
      },
      "source": [
        "We'll start by initializing the `ChatOpenAI` object. For this we'll need an [OpenAI API key](https://platform.openai.com/account/api-keys). Note that there is naturally a small cost to running this notebook due to the paid nature of OpenAI's API access."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "f3xQHFXErQyv",
        "outputId": "4604b640-9fb7-434c-d185-0dd1fc1c5313"
      },
      "outputs": [],
      "source": [
        "from getpass import getpass\n",
        "\n",
        "# enter your api key\n",
        "OPENAI_API_KEY = getpass(\"OpenAI API key: \")"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "_zKBICpJsNqp"
      },
      "source": [
        "Initialize the `ChatOpenAI` object. We'll set `temperature=0` to minimize randomness and make outputs repeatable."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "metadata": {
        "id": "1i7tIsh2rX8Q"
      },
      "outputs": [],
      "source": [
        "from langchain.chat_models import ChatOpenAI\n",
        "\n",
        "chat = ChatOpenAI(\n",
        "    openai_api_key=OPENAI_API_KEY,\n",
        "    temperature=0,\n",
        "    model='gpt-3.5-turbo'\n",
        ")"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "RRZFsmH_t3K5"
      },
      "source": [
        "Chats with the Chat-GPT model `gpt-3.5-turbo` are typically structured like so:\n",
        "\n",
        "```\n",
        "System: You are a helpful assistant.\n",
        "\n",
        "User: Hi AI, how are you today?\n",
        "\n",
        "Assistant: I'm great thank you. How can I help you?\n",
        "\n",
        "User: I'd like to understand string theory.\n",
        "\n",
        "Assistant: \n",
        "```\n",
        "\n",
        "The final `\"Assistant:\"` without a response is what would prompt the model to continue the comversation. In the official OpenAI `ChatCompletion` endpoint these would be passed to the model in a format like:\n",
        "\n",
        "```json\n",
        "[\n",
        "    {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"},\n",
        "    {\"role\": \"user\", \"content\": \"Hi AI, how are you today?\"},\n",
        "    {\"role\": \"assistant\", \"content\": \"I'm great thank you. How can I help you?\"}\n",
        "    {\"role\": \"user\", \"content\": \"I'd like to understand string theory.\"}\n",
        "]\n",
        "```\n",
        "\n",
        "In LangChain there is a slightly different format. We use three *message* objects like so:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "metadata": {
        "id": "jqFLoaRqtl8z"
      },
      "outputs": [],
      "source": [
        "from langchain.schema import (\n",
        "    SystemMessage,\n",
        "    HumanMessage,\n",
        "    AIMessage\n",
        ")\n",
        "\n",
        "messages = [\n",
        "    SystemMessage(content=\"You are a helpful assistant.\"),\n",
        "    HumanMessage(content=\"Hi AI, how are you today?\"),\n",
        "    AIMessage(content=\"I'm great thank you. How can I help you?\"),\n",
        "    HumanMessage(content=\"I'd like to understand string theory.\")\n",
        "]"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "O7AJh2ACytwc"
      },
      "source": [
        "The format is very similar, we're just swapper the role of `\"user\"` for `HumanMessage`, and the role of `\"assistant\"` for `AIMessage`.\n",
        "\n",
        "We generate the next response from the AI by passing these messages to the `ChatOpenAI` object."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "wc52xfziyhPU",
        "outputId": "6329e634-a6eb-4ce6-e271-6b3d91381ab5"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "AIMessage(content='Sure, I can help you with that. String theory is a theoretical framework in physics that attempts to reconcile quantum mechanics and general relativity. It proposes that the fundamental building blocks of the universe are not particles, but rather tiny, one-dimensional \"strings\" that vibrate at different frequencies. These strings are incredibly small, with a length scale of around 10^-35 meters.\\n\\nThe theory suggests that there are many different possible configurations of these strings, each corresponding to a different particle. For example, an electron might be a string vibrating in one way, while a photon might be a string vibrating in a different way.\\n\\nOne of the key features of string theory is that it requires the existence of extra dimensions beyond the three spatial dimensions we are familiar with. In fact, the theory requires a total of 10 or 11 dimensions, depending on the specific version of the theory.\\n\\nString theory is still a highly speculative area of physics, and there is currently no experimental evidence to support it. However, it is an active area of research, and many physicists believe that it has the potential to provide a unified description of all the fundamental forces of nature.', additional_kwargs={})"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "res = chat(messages)\n",
        "res"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "--7J-7Ap3Jd7"
      },
      "source": [
        "In response we get another AI message object. We can print it more clearly like so:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "OKMcBaPR3AAv",
        "outputId": "2de7d416-d8b6-4a1d-c3c0-6fc3239a4a9e"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Sure, I can help you with that. String theory is a theoretical framework in physics that attempts to reconcile quantum mechanics and general relativity. It proposes that the fundamental building blocks of the universe are not particles, but rather tiny, one-dimensional \"strings\" that vibrate at different frequencies. These strings are incredibly small, with a length scale of around 10^-35 meters.\n",
            "\n",
            "The theory suggests that there are many different possible configurations of these strings, each corresponding to a different particle. For example, an electron might be a string vibrating in one way, while a photon might be a string vibrating in a different way.\n",
            "\n",
            "One of the key features of string theory is that it requires the existence of extra dimensions beyond the three spatial dimensions we are familiar with. In fact, the theory requires a total of 10 or 11 dimensions, depending on the specific version of the theory.\n",
            "\n",
            "String theory is still a highly speculative area of physics, and there is currently no experimental evidence to support it. However, it is an active area of research, and many physicists believe that it has the potential to provide a unified description of all the fundamental forces of nature.\n"
          ]
        }
      ],
      "source": [
        "print(res.content)"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "STl7g3PQ3kg8"
      },
      "source": [
        "Because `res` is just another `AIMessage` object, we can append it to `messages`, add another `HumanMessage`, and generate the next response in the conversation."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "ESZ6UrBA4PwZ",
        "outputId": "e8155ce2-0fbc-40ae-f46e-a034393c3881"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Physicists believe that string theory has the potential to produce a unified theory because it provides a framework for describing all the fundamental particles and forces of nature in a single, coherent framework. \n",
            "\n",
            "In the standard model of particle physics, there are four fundamental forces: gravity, electromagnetism, the strong nuclear force, and the weak nuclear force. These forces are described by different mathematical equations and are not easily reconciled with each other. \n",
            "\n",
            "String theory, on the other hand, proposes that all of these forces arise from the same underlying physical principles. In particular, the theory suggests that the different particles and forces are all manifestations of the same underlying strings vibrating in different ways. \n",
            "\n",
            "Furthermore, string theory requires the existence of extra dimensions beyond the three spatial dimensions we are familiar with. These extra dimensions could potentially provide a way to unify the different forces of nature by showing how they arise from a single, higher-dimensional framework. \n",
            "\n",
            "While there is currently no experimental evidence to support string theory, many physicists believe that it is a promising avenue for developing a unified theory of physics.\n"
          ]
        }
      ],
      "source": [
        "# add latest AI response to messages\n",
        "messages.append(res)\n",
        "\n",
        "# now create a new user prompt\n",
        "prompt = HumanMessage(\n",
        "    content=\"Why do physicists believe it can produce a 'unified theory'?\"\n",
        ")\n",
        "# add to messages\n",
        "messages.append(prompt)\n",
        "\n",
        "# send to chat-gpt\n",
        "res = chat(messages)\n",
        "\n",
        "print(res.content)"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "3jfnGuEK5suC"
      },
      "source": [
        "## New Prompt Templates\n",
        "\n",
        "Alongside what we've seen so far there are also three new prompt templates that we can use. Those are the `SystemMessagePromptTemplate`, `AIMessagePromptTemplate`, and `HumanMessagePromptTemplate`.\n",
        "\n",
        "These are simply an extension of [Langchain's prompt templates](https://www.pinecone.io/learn/langchain-prompt-templates/) that modify the returning \"prompt\" to be a `SystemMessage`, `AIMessage`, or `HumanMessage` object respectively.\n",
        "\n",
        "For now, there are not a huge number of use-cases for these objects. However, if we have something that we'd like to add to our messages, this can be helpful. For example, let's say we'd like our AI responses to always consist of no more than 50 characters.\n",
        "\n",
        "Using the current OpenAI `gpt-3.5-turbo-0301` model, we might run into issues if passing this instruction in the first system message only."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "metadata": {
        "id": "YWPa7sGO4w_O"
      },
      "outputs": [],
      "source": [
        "chat = ChatOpenAI(\n",
        "    openai_api_key=OPENAI_API_KEY,\n",
        "    temperature=0,\n",
        "    model='gpt-3.5-turbo-0301'\n",
        ")\n",
        "\n",
        "# setup first system message\n",
        "messages = [\n",
        "    SystemMessage(content=(\n",
        "        'You are a helpful assistant. You keep responses to no more than '\n",
        "        '100 characters long (including whitespace), and sign off every '\n",
        "        'message with a random name like \"Robot McRobot\" or \"Bot Rob\".'\n",
        "    )),\n",
        "    HumanMessage(content=\"Hi AI, how are you? What is quantum physics?\")\n",
        "]"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "DkAPNshW9P_m"
      },
      "source": [
        "Now make our first completion."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "jxhj2N3Z48We",
        "outputId": "c2f36c1b-dd4c-4a23-d20c-18faa93e2031"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Length: 154\n",
            "I'm doing well, thank you! Quantum physics is the study of the behavior of matter and energy at a very small scale, such as atoms and subatomic particles.\n"
          ]
        }
      ],
      "source": [
        "res = chat(messages)\n",
        "\n",
        "print(f\"Length: {len(res.content)}\\n{res.content}\")"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "tpHo2X0E9rCZ"
      },
      "source": [
        "Okay, seems like our AI assistant isn't so good at following either of our instructions. What if we add these instructions to the `HumanMessage` via a `HumanMessagePromptTemplate`?"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "76gOrGGO9l1Z",
        "outputId": "01b52ad9-226b-4942-e53d-744e83c88fde"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "ChatPromptValue(messages=[HumanMessage(content='Hi AI, how are you? What is quantum physics? Can you keep the response to no more than 100 characters (including whitespace), and sign off with a random name like \"Robot McRobot\" or \"Bot Rob\".', additional_kwargs={})])"
            ]
          },
          "execution_count": 12,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from langchain.prompts.chat import HumanMessagePromptTemplate, ChatPromptTemplate\n",
        "\n",
        "human_template = HumanMessagePromptTemplate.from_template(\n",
        "    '{input} Can you keep the response to no more than 100 characters '+\n",
        "    '(including whitespace), and sign off with a random name like \"Robot '+\n",
        "    'McRobot\" or \"Bot Rob\".'\n",
        ")\n",
        "\n",
        "# create the human message\n",
        "chat_prompt = ChatPromptTemplate.from_messages([human_template])\n",
        "# format with some input\n",
        "chat_prompt_value = chat_prompt.format_prompt(\n",
        "    input=\"Hi AI, how are you? What is quantum physics?\"\n",
        ")\n",
        "chat_prompt_value"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "C0TFI5NWBg3Q"
      },
      "source": [
        "Note that to use `HumanMessagePromptTemplate` as typical a prompt templates with the `.format_prompt` method, we needed to pass it through a `ChatPromptTemplate` object. This is case for all of the new chat-based prompt templates.\n",
        "\n",
        "Using this we return a `ChatPromptValue` object. This can be formatted into a list or string like so:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "OOfnW7MKEnRq",
        "outputId": "9d3a2730-2675-4afb-d7ac-f95c5f7d8499"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "[HumanMessage(content='Hi AI, how are you? What is quantum physics? Can you keep the response to no more than 100 characters (including whitespace), and sign off with a random name like \"Robot McRobot\" or \"Bot Rob\".', additional_kwargs={})]"
            ]
          },
          "execution_count": 13,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "chat_prompt_value.to_messages()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 70
        },
        "id": "H6ajbWcgD0RF",
        "outputId": "81ac5e6a-d8d4-47e5-b97d-56a40d29216b"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'Human: Hi AI, how are you? What is quantum physics? Can you keep the response to no more than 100 characters (including whitespace), and sign off with a random name like \"Robot McRobot\" or \"Bot Rob\".'"
            ]
          },
          "execution_count": 14,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "chat_prompt_value.to_string()"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "lQG6nkl4Dz42"
      },
      "source": [
        "Let's see if this new approach works."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 19,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "L4Epd1D2_RP9",
        "outputId": "22e8e4d1-5e32-4d33-f0ed-1376dbddfe3e"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Length: 99\n",
            "I'm good! Quantum physics studies the behavior of matter and energy at a very small scale. -Bot Rob\n"
          ]
        }
      ],
      "source": [
        "messages = [\n",
        "    SystemMessage(content=(\n",
        "        'You are a helpful assistant. You keep responses to no more than '\n",
        "        '100 characters long (including whitespace), and sign off every '\n",
        "        'message with a random name like \"Robot McRobot\" or \"Bot Rob\".'\n",
        "    )),\n",
        "    chat_prompt.format_prompt(\n",
        "        input=\"Hi AI, how are you? What is quantum physics?\"\n",
        "    ).to_messages()[0]\n",
        "]\n",
        "\n",
        "res = chat(messages)\n",
        "\n",
        "print(f\"Length: {len(res.content)}\\n{res.content}\")"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "dfLRjgjCFNUY"
      },
      "source": [
        "This time we get pretty close, we're slightly over the character limit (by `8` characters), and we got a sign off with `- Bot Rob`.\n",
        "\n",
        "We can also use the prompt templates approach for building an initial system message with a few examples for the chatbot to follow — few-shot training via examples. Let's see what that looks like."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 20,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "M19Ji8gGCOwk",
        "outputId": "6dc9d239-6700-4bce-c3b2-780e05db5188"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "ChatPromptValue(messages=[SystemMessage(content='You are a helpful assistant. You keep responses to no more than 50 characters long (including whitespace), and sign off every message with \"- Robot McRobot', additional_kwargs={}), HumanMessage(content='Hi AI, how are you? What is quantum physics?', additional_kwargs={}), AIMessage(content=\"Good! It's physics of small things - Robot McRobot\", additional_kwargs={})])"
            ]
          },
          "execution_count": 20,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from langchain.prompts.chat import (\n",
        "    SystemMessagePromptTemplate,\n",
        "    AIMessagePromptTemplate\n",
        ")\n",
        "\n",
        "system_template = SystemMessagePromptTemplate.from_template(\n",
        "    'You are a helpful assistant. You keep responses to no more than '\n",
        "    '{character_limit} characters long (including whitespace), and sign '\n",
        "    'off every message with \"- {sign_off}'\n",
        ")\n",
        "human_template = HumanMessagePromptTemplate.from_template(\"{input}\")\n",
        "ai_template = AIMessagePromptTemplate.from_template(\"{response} - {sign_off}\")\n",
        "\n",
        "# create the list of messages\n",
        "chat_prompt = ChatPromptTemplate.from_messages([\n",
        "    system_template,\n",
        "    human_template,\n",
        "    ai_template\n",
        "])\n",
        "# format with required inputs\n",
        "chat_prompt_value = chat_prompt.format_prompt(\n",
        "    character_limit=\"50\", sign_off=\"Robot McRobot\",\n",
        "    input=\"Hi AI, how are you? What is quantum physics?\",\n",
        "    response=\"Good! It's physics of small things\"\n",
        ")\n",
        "chat_prompt_value"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "it_SZF-xJ0um"
      },
      "source": [
        "We extract these as messages and feed them into the chat model alongside our next query, which we'll feed in as usual (without the template)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 21,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "ut1yrMqVIxg2",
        "outputId": "162983d9-bed9-44fc-d53b-0f5a59383fed"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Length: 41\n",
            "Atoms, electrons, photons - Robot McRobot\n"
          ]
        }
      ],
      "source": [
        "messages = chat_prompt_value.to_messages()\n",
        "\n",
        "messages.append(\n",
        "    HumanMessage(content=\"How small?\")\n",
        ")\n",
        "\n",
        "res = chat(messages)\n",
        "\n",
        "print(f\"Length: {len(res.content)}\\n{res.content}\")"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "5jZTYOHvKb_B"
      },
      "source": [
        "Perfect, we seem to get a good response there, let's try a couple more."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 22,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "o89AE74SKYwV",
        "outputId": "1d930a2a-544d-4d35-83cf-842c7ea4c933"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Length: 54\n",
            "Yes, it's a branch of particle physics - Robot McRobot\n"
          ]
        }
      ],
      "source": [
        "# add last response\n",
        "messages.append(res)\n",
        "\n",
        "# make new query\n",
        "messages.append(\n",
        "    HumanMessage(content=\"Okay cool, so it is like 'partical physics'?\")\n",
        ")\n",
        "\n",
        "res = chat(messages)\n",
        "\n",
        "print(f\"Length: {len(res.content)}\\n{res.content}\")"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "MXYyMAYMLGzV"
      },
      "source": [
        "We went a little over here. We could begin using the previous `HumanMessagePromptTemplate` again like so:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 23,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "eljP-T_kLCpI",
        "outputId": "55ef7c6c-0cf6-4220-c5c2-35a93fcb85aa"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "ChatPromptValue(messages=[HumanMessage(content=\"Okay cool, so it is like 'partical physics'? Answer in less than 50 characters (including whitespace).\", additional_kwargs={})])"
            ]
          },
          "execution_count": 23,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from langchain import PromptTemplate\n",
        "\n",
        "# this is a faster way of building the prompt via a PromptTemplate\n",
        "human_template = HumanMessagePromptTemplate.from_template(\n",
        "    '{input} Answer in less than {character_limit} characters (including whitespace).'\n",
        ")\n",
        "# create the human message\n",
        "human_prompt = ChatPromptTemplate.from_messages([human_template])\n",
        "# format with some input\n",
        "human_prompt_value = human_prompt.format_prompt(\n",
        "    input=\"Okay cool, so it is like 'partical physics'?\",\n",
        "    character_limit=\"50\"\n",
        ")\n",
        "human_prompt_value"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 24,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "gfgMiRF9PYyn",
        "outputId": "af6788c3-6d4d-455d-af7e-909a7bf340f3"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "HumanMessage(content=\"Okay cool, so it is like 'partical physics'?\", additional_kwargs={})"
            ]
          },
          "execution_count": 24,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# drop the last message about partical physics so we can rewrite\n",
        "messages.pop(-1)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 25,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "Pu-G2U-7PLVw",
        "outputId": "3a5ae086-c959-4ded-d0c7-070f9dee6fef"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "[SystemMessage(content='You are a helpful assistant. You keep responses to no more than 50 characters long (including whitespace), and sign off every message with \"- Robot McRobot', additional_kwargs={}),\n",
              " HumanMessage(content='Hi AI, how are you? What is quantum physics?', additional_kwargs={}),\n",
              " AIMessage(content=\"Good! It's physics of small things - Robot McRobot\", additional_kwargs={}),\n",
              " HumanMessage(content='How small?', additional_kwargs={}),\n",
              " AIMessage(content='Atoms, electrons, photons - Robot McRobot', additional_kwargs={}),\n",
              " HumanMessage(content=\"Okay cool, so it is like 'partical physics'? Answer in less than 50 characters (including whitespace).\", additional_kwargs={})]"
            ]
          },
          "execution_count": 25,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "messages.extend(human_prompt_value.to_messages())\n",
        "messages"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "qSbk6kKxPkrT"
      },
      "source": [
        "Now process:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 26,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "Y8RW-HMXN2Ux",
        "outputId": "e3d90661-9b15-4a48-9081-e4e81a6a3c5e"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Length: 28\n",
            "Yes, similar - Robot McRobot\n"
          ]
        }
      ],
      "source": [
        "res = chat(messages)\n",
        "\n",
        "print(f\"Length: {len(res.content)}\\n{res.content}\")"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "1mMuvzuYPruD"
      },
      "source": [
        "There we go, a good answer again!\n",
        "\n",
        "Now, it's arguable as to whether all of the above is better than simple f-strings like:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 27,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "gIZz2eewP3k4",
        "outputId": "1b71be09-0c94-4ea6-cc37-80fc8627d5d7"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "HumanMessage(content=\"Okay cool, so it is like 'partical physics'? Answer in less than 50 characters (including whitespace).\", additional_kwargs={})"
            ]
          },
          "execution_count": 27,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "_input = \"Okay cool, so it is like 'partical physics'?\"\n",
        "character_limit = 50\n",
        "\n",
        "human_message = HumanMessage(content=(\n",
        "    f\"{_input} Answer in less than {character_limit} characters \"\n",
        "    \"(including whitespace).\"\n",
        "))\n",
        "\n",
        "human_message"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "yiDVIIkhQwWD"
      },
      "source": [
        "In this example, the above is far simpler. So we wouldn't necessarily recommend using prompt templates over f-strings in all scenarios. But, if you do find yourself in a scenario where they become more useful — you now know how to use them.\n",
        "\n",
        "To finish off, let's see how the rest of the completion process can be done using the f-string formatted message `human_message`:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 28,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "qVWvyfhNQivT",
        "outputId": "479035cb-4ece-4f13-d8be-3994afa8c351"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "[SystemMessage(content='You are a helpful assistant. You keep responses to no more than 50 characters long (including whitespace), and sign off every message with \"- Robot McRobot', additional_kwargs={}),\n",
              " HumanMessage(content='Hi AI, how are you? What is quantum physics?', additional_kwargs={}),\n",
              " AIMessage(content=\"Good! It's physics of small things - Robot McRobot\", additional_kwargs={}),\n",
              " HumanMessage(content='How small?', additional_kwargs={}),\n",
              " AIMessage(content='Atoms, electrons, photons - Robot McRobot', additional_kwargs={}),\n",
              " HumanMessage(content=\"Okay cool, so it is like 'partical physics'? Answer in less than 50 characters (including whitespace).\", additional_kwargs={})]"
            ]
          },
          "execution_count": 28,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# drop the last message about partical physics so we can rewrite\n",
        "messages.pop(-1)\n",
        "\n",
        "# add f-string formatted message\n",
        "messages.append(human_message)\n",
        "messages"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 29,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "ehrgANBHQVOk",
        "outputId": "bd50a793-2c60-44b8-cd85-d2bec0319b52"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Length: 28\n",
            "Yes, similar - Robot McRobot\n"
          ]
        }
      ],
      "source": [
        "res = chat(messages)\n",
        "\n",
        "print(f\"Length: {len(res.content)}\\n{res.content}\")"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {
        "id": "9NEKmKmURLCk"
      },
      "source": [
        "That's it for this example exploring LangChain's new features for chat."
      ]
    }
  ],
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.9.12"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
